/**
 * WMS/WMTS服务工具类
 * 提供WMS和WMTS服务的解析、加载和管理功能
 */
import * as Cesium from 'cesium'
import convert from 'xml-js'

class WmsWmtsUtils {
  /**
   * 构造函数
   * @param {Object} viewer - Cesium Viewer实例
   */
  constructor(viewer) {
    this.viewer = viewer
    this.loadedLayers = new Map() // 存储已加载的图层信息
    this.layerIdCounter = 0 // 用于生成唯一的图层ID
  }

  /**
   * 从WMTS服务URL解析参数
   * @param {string} xmlUrl - WMTS服务的XML描述文件URL
   * @returns {Promise<Array>} 解析后的WMTS服务参数数组
   */
  async getWMTSParamsFromUrl(xmlUrl) {
    try {
      // 以文本方式获取XML文件
      const response = await fetch(xmlUrl)
      const xmlText = await response.text()
      
      // 解析XML为JS对象
      const option = {
        ignoreDeclaration: true,
        compact: true,
        trim: true,
        ignoreInstruction: true,
        ignoreComment: true,
        ignoreCdata: true,
        ignoreDoctype: true,
        textFn: this._removeJsonTextAttribute
      }
      
      const xmlObj = convert.xml2js(xmlText, option)
      return this._getWMTSInfo(xmlObj)
    } catch (error) {
      console.error('解析WMTS服务失败:', error)
      throw error
    }
  }

  /**
   * 移除JSON对象中的_text属性
   * @private
   */
  _removeJsonTextAttribute(value, parentElement) {
    try {
      const keyNo = Object.keys(parentElement._parent).length
      const keyName = Object.keys(parentElement._parent)[keyNo - 1]
      parentElement._parent[keyName] = value
    } catch (e) {}
  }

  /**
   * 从解析后的XML对象中提取WMTS服务信息
   * @private
   */
  _getWMTSInfo(obj) {
    const WMTSXML = 'http://www.opengis.net/wmts/1.0'
    const wmtsList = []
    
    if (obj.Capabilities) {
      const { _attributes, Contents } = obj.Capabilities
      if (_attributes?.xmlns !== WMTSXML) {
        return []
      }
      
      const { Layer, TileMatrixSet } = Contents
      if (!Layer || !TileMatrixSet) {
        return []
      }
      
      const tileSet = TileMatrixSet[0]
      const tileMatrixSetID = tileSet['ows:Identifier']
      const crs = tileSet['ows:SupportedCRS']
      const tileMatrixLabels = tileSet.TileMatrix?.map(s => s['ows:Identifier']) || []
      
      let LayerInfo = Layer
      if (!Array.isArray(LayerInfo)) {
        LayerInfo = [LayerInfo]
      }
      
      LayerInfo.forEach(layer => {
        let resourceURL = layer?.ResourceURL
        if (!resourceURL) return
        
        if (!Array.isArray(resourceURL)) {
          resourceURL = [resourceURL]
        }
        
        const format = 'image/png' || layer?.Format
        const resourceURLItem = resourceURL.filter(s => s._attributes.resourceType === 'tile')
        let pngResource = resourceURLItem.find(s => s._attributes.format?.endsWith('png')) || resourceURLItem[0]
        
        if (!pngResource) return
        
        const info = {
          url: pngResource?._attributes?.template,
          layer: layer['ows:Identifier'],
          style: layer.Style?.['ows:Identifier'],
          tileMatrixSetID: tileMatrixSetID,
          format: pngResource?._attributes?.format || format,
          tileMatrixLabels: tileMatrixLabels,
          crs: crs
        }
        
        // 获取服务范围
        if (layer['ows:WGS84BoundingBox']) {
          const wgsBox = layer['ows:WGS84BoundingBox']
          const lower = wgsBox['ows:LowerCorner'].split(' ').map(s => Number(s))
          const upper = wgsBox['ows:UpperCorner'].split(' ').map(s => Number(s))
          const center = [lower[0] + (upper[0] - lower[0]) / 2, lower[1] + (upper[1] - lower[1]) / 2]
          info.center = center
          info.bounds = {
            west: lower[0],
            south: lower[1],
            east: upper[0],
            north: upper[1]
          }
        }
        
        wmtsList.push(info)
      })
    }
    
    return wmtsList
  }

  /**
   * 创建WMTS图层提供者
   * @param {Object} params - WMTS服务参数
   * @returns {Cesium.WebMapTileServiceImageryProvider} WMTS图层提供者
   */
  createWMTSProvider(params) {
    const { url, layer, style, tileMatrixSetID, format, maximumLevel = 18, minimumLevel = 0 } = params
    
    // 创建配置对象
    const providerConfig = {
      url: url,
      layer: layer,
      style: style || 'default',
      format: format || 'image/png',
      tileMatrixSetID: tileMatrixSetID,
      maximumLevel: maximumLevel,
      minimumLevel: minimumLevel,
      credit: new Cesium.Credit(`WMTS: ${layer}`)
    }
    
    // 处理4326坐标系的特殊情况
    if (params.crs === 'CRS:84' || params.crs === 'EPSG:4326') {
      providerConfig.tilingScheme = new Cesium.GeographicTilingScheme({
        numberOfLevelZeroTilesX: 2,
        numberOfLevelZeroTilesY: 1,
        ellipsoid: Cesium.Ellipsoid.WGS84,
        rectangle: Cesium.Rectangle.fromDegrees(-180.0, -90.0, 180.0, 90.0)
      })
    }
    
    // 如果提供了tileMatrixLabels，添加到配置中
    if (params.tileMatrixLabels && Array.isArray(params.tileMatrixLabels)) {
      providerConfig.tileMatrixLabels = params.tileMatrixLabels
    }
    
    return new Cesium.WebMapTileServiceImageryProvider(providerConfig)
  }

  /**
   * 创建WMS图层提供者
   * @param {Object} params - WMS服务参数
   * @returns {Cesium.WebMapServiceImageryProvider} WMS图层提供者
   */
  createWMSProvider(params) {
    const { url, layers, styles, crs, format = 'image/png', transparent = true } = params
    
    return new Cesium.WebMapServiceImageryProvider({
      url: url,
      layers: layers,
      styles: styles || '',
      format: format,
      transparent: transparent,
      crs: crs || 'EPSG:4326',
      credit: new Cesium.Credit(`WMS: ${layers}`)
    })
  }

  /**
   * 从URL加载WMTS服务
   * @param {string} xmlUrl - WMTS服务的XML描述文件URL
   * @param {Object} layerOptions - 图层选项（透明度、zIndex等）
   * @returns {Promise<Array>} 加载的图层ID数组
   */
  async loadWMTSFromUrl(xmlUrl, layerOptions = {}) {
    if (!this.viewer) {
      throw new Error('Viewer实例未提供')
    }
    
    try {
      const wmtsServices = await this.getWMTSParamsFromUrl(xmlUrl)
      const loadedLayerIds = []
      
      for (const serviceParams of wmtsServices) {
        const layerId = await this.addWMTSLayer(serviceParams, layerOptions)
        loadedLayerIds.push(layerId)
      }
      
      return loadedLayerIds
    } catch (error) {
      console.error('从URL加载WMTS服务失败:', error)
      throw error
    }
  }

  /**
   * 添加WMTS图层
   * @param {Object} params - WMTS服务参数
   * @param {Object} layerOptions - 图层选项
   * @returns {string} 图层ID
   */
  async addWMTSLayer(params, layerOptions = {}) {
    if (!this.viewer) {
      throw new Error('Viewer实例未提供')
    }
    
    try {
      const provider = this.createWMTSProvider(params)
      const layerId = `wmts_${this.layerIdCounter++}`
      
      const imageryLayer = new Cesium.ImageryLayer(provider, {
        alpha: layerOptions.alpha || 1.0,
        zIndex: layerOptions.zIndex || 0,
        show: layerOptions.show !== false
      })
      
      this.viewer.imageryLayers.add(imageryLayer)
      
      // 存储图层信息
      this.loadedLayers.set(layerId, {
        id: layerId,
        type: 'wmts',
        params: params,
        layer: imageryLayer,
        name: params.layer || `WMTS Layer ${layerId}`
      })
      
      console.log(`成功添加WMTS图层: ${params.layer || layerId}`)
      
      // 如果提供了中心点，调整相机视角
      if (params.center && layerOptions.flyTo) {
        this.viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(params.center[0], params.center[1], layerOptions.zoom || 1000000),
          duration: 1.5
        })
      }
      
      return layerId
    } catch (error) {
      console.error('添加WMTS图层失败:', error)
      throw error
    }
  }

  /**
   * 添加WMS图层
   * @param {Object} params - WMS服务参数
   * @param {Object} layerOptions - 图层选项
   * @returns {string} 图层ID
   */
  addWMSLayer(params, layerOptions = {}) {
    if (!this.viewer) {
      throw new Error('Viewer实例未提供')
    }
    
    try {
      const provider = this.createWMSProvider(params)
      const layerId = `wms_${this.layerIdCounter++}`
      
      const imageryLayer = new Cesium.ImageryLayer(provider, {
        alpha: layerOptions.alpha || 1.0,
        zIndex: layerOptions.zIndex || 0,
        show: layerOptions.show !== false
      })
      
      this.viewer.imageryLayers.add(imageryLayer)
      
      // 存储图层信息
      this.loadedLayers.set(layerId, {
        id: layerId,
        type: 'wms',
        params: params,
        layer: imageryLayer,
        name: params.layers || `WMS Layer ${layerId}`
      })
      
      console.log(`成功添加WMS图层: ${params.layers || layerId}`)
      
      return layerId
    } catch (error) {
      console.error('添加WMS图层失败:', error)
      throw error
    }
  }

  /**
   * 移除图层
   * @param {string} layerId - 图层ID
   * @returns {boolean} 是否成功移除
   */
  removeLayer(layerId) {
    if (!this.viewer || !this.loadedLayers.has(layerId)) {
      return false
    }
    
    try {
      const layerInfo = this.loadedLayers.get(layerId)
      this.viewer.imageryLayers.remove(layerInfo.layer)
      this.loadedLayers.delete(layerId)
      
      console.log(`成功移除图层: ${layerInfo.name}`)
      return true
    } catch (error) {
      console.error('移除图层失败:', error)
      return false
    }
  }

  /**
   * 显示/隐藏图层
   * @param {string} layerId - 图层ID
   * @param {boolean} show - 是否显示
   * @returns {boolean} 操作是否成功
   */
  showLayer(layerId, show) {
    if (!this.loadedLayers.has(layerId)) {
      return false
    }
    
    try {
      const layerInfo = this.loadedLayers.get(layerId)
      layerInfo.layer.show = show
      return true
    } catch (error) {
      console.error('显示/隐藏图层失败:', error)
      return false
    }
  }

  /**
   * 更新图层透明度
   * @param {string} layerId - 图层ID
   * @param {number} alpha - 透明度 (0-1)
   * @returns {boolean} 操作是否成功
   */
  setLayerOpacity(layerId, alpha) {
    if (!this.loadedLayers.has(layerId)) {
      return false
    }
    
    try {
      const layerInfo = this.loadedLayers.get(layerId)
      layerInfo.layer.alpha = alpha
      return true
    } catch (error) {
      console.error('更新图层透明度失败:', error)
      return false
    }
  }

  /**
   * 获取所有已加载的图层信息
   * @returns {Array} 图层信息数组
   */
  getLoadedLayers() {
    return Array.from(this.loadedLayers.values()).map(layer => ({
      id: layer.id,
      type: layer.type,
      name: layer.name,
      params: layer.params
    }))
  }

  /**
   * 清理资源
   */
  destroy() {
    // 移除所有加载的图层
    this.loadedLayers.forEach((layerInfo, layerId) => {
      this.removeLayer(layerId)
    })
    
    this.loadedLayers.clear()
    this.viewer = null
  }
}

export default WmsWmtsUtils